package service

import (
	"errors"
	"github.com/dgrijalva/jwt-go"
	"time"
)

type JwtIn interface {
	CreateToken() (*Token, error)
	ParserToken(tokenString string) (*AccessTokenClaims, error)
	ParserIdToken(tokenString string) (*IdTokenClaims, error)
}

type Token struct {
	ExpiresTime time.Time
	Token       string
}

type IdTokenClaims struct {
	Uid       int    `json:"uid"`
	UserNames string `json:"user_names"`
	Email     string `json:"email"`
	Phone     int    `json:"phone"`
	jwt.StandardClaims
}

type AccessTokenClaims struct {
	jwt.StandardClaims
}

const PrivateKey = "lightos"

func (claim *AccessTokenClaims) CreateToken() (*Token, error) {
	ExpiresTime := time.Now().Add(1 * time.Hour)
	claim.ExpiresAt = ExpiresTime.Unix()
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claim)
	signedString, err := token.SignedString([]byte(PrivateKey))
	return &Token{
		ExpiresTime: ExpiresTime,
		Token:       signedString,
	}, err
}

//AccessTokenClaims主要是提供一个模板
func (claim *AccessTokenClaims) ParserToken(tokenString string) (*AccessTokenClaims, error) {
	token, err := jwt.ParseWithClaims(tokenString, &AccessTokenClaims{}, func(token *jwt.Token) (interface{}, error) {
		return PrivateKey, nil
	})

	if token != nil {
		if claims, ok := token.Claims.(*AccessTokenClaims); ok && token.Valid {
			return claims, nil
		}
	}
	return nil, err
}

func (claim *AccessTokenClaims) ParserIdToken(tokenString string) (*IdTokenClaims, error) {
	tokenString = ""
	return nil, errors.New("Nonsupport for this claim")
}

func (claim *IdTokenClaims) CreateToken() (*Token, error) {
	ExpiresTime := time.Now().Add(1 * time.Hour)
	claim.ExpiresAt = ExpiresTime.Unix()
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claim)
	signedString, err := token.SignedString([]byte(PrivateKey))
	return &Token{
		ExpiresTime: ExpiresTime,
		Token:       signedString,
	}, err
}

func (claim *IdTokenClaims) ParserToken(tokenString string) (*AccessTokenClaims, error) {
	tokenString = ""
	return nil, errors.New("Nonsupport for this claim")
}

func (claim *IdTokenClaims) ParserIdToken(tokenString string) (*IdTokenClaims, error) {
	token, err := jwt.ParseWithClaims(tokenString, &IdTokenClaims{}, func(token *jwt.Token) (interface{}, error) {
		return PrivateKey, nil
	})

	if token != nil {
		if claims, ok := token.Claims.(*IdTokenClaims); ok && token.Valid {
			return claims, nil
		}
	}
	return nil, err
}
